#pragma once 
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<unistd.h>
#include <iostream>
#include <functional>
#include <string>
#include <signal.h>

#include "HandlerData.hpp"
#include "Task.hpp"
#include "ThreadPool.hpp"
#include "Log.hpp"

enum {
    USAG_ERR = 1,
    SOCK_ERR,
    BIND_ERR,
    LSITEN_ERR
};
#define PORT 8080
 
namespace wyl
{

      //typedef std::function<void(const Request& req,Response& resp)> func_t;
    

    class TcpServer
    {
    public:
        TcpServer(func_t hdl, uint16_t port = PORT) :
        _handler(hdl), _list_sock(-1),_port(port),_inbuff(""){}
        ~TcpServer(){close(_list_sock);}

        void init()
        {
            //1.创建套接字
            _list_sock = socket(AF_INET,SOCK_STREAM,0);
            if(_list_sock < 0)
            {
                logMessage(FATAL,"listsock created fail: %d",_list_sock);
                exit(SOCK_ERR);
            }
            logMessage(NORMAL,"listsock created success: %d",_list_sock);

            //2.绑定套接字
            struct sockaddr_in svr;
            svr.sin_port = htons(_port); 
            svr.sin_addr.s_addr = INADDR_ANY;
            svr.sin_family = AF_INET; 
            if(bind(_list_sock,(struct sockaddr*)&svr,sizeof svr) != 0)
            {
                logMessage(FATAL,"listsock bind fail");
                exit(BIND_ERR);
            }
            logMessage(NORMAL,"listsock bind success: %d",_list_sock);

            //3.监听套接字
            if(listen(_list_sock,5) != 0)
            {
                logMessage(FATAL,"listsock listen fail");
                exit(LSITEN_ERR);
            }
            logMessage(NORMAL,"listsock listen success: %d",_list_sock);
            int opt = 1;
            if(setsockopt(_list_sock,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT,(void*)&opt,sizeof opt))
                logMessage(WARING,"reuser port failed");

        }

        void start()
        {
   
            signal(SIGCHLD,SIG_IGN);
            //会话层
            while(1)
            {
                //Accept获取连接，没有连接到来则阻塞
                struct sockaddr_in peer;
                socklen_t peer_len = sizeof peer;
                int new_sock = accept(_list_sock,(struct sockaddr*)&peer,&peer_len);
                if(new_sock < 0)
                {
                    logMessage(WARING,"listsock accept fail");
                    continue;
                }
                logMessage(NORMAL,"accept success  new sock : %d",new_sock);
                
                //char buff[10*4048] = {0};
                //多进程版
                // if(fork() == 0)
                // {
                //     close(_list_sock);
                //     if(fork() > 0) exit(0);
                //     //读取数据
                //     logMessage(NORMAL,"begin read......");
                //     int n = read(new_sock,buff,sizeof buff - 1); 
                //     logMessage(NORMAL,"read  end......");
                //     if(n > 0)
                //     {
                //         _inbuff += buff;
                //         logMessage(NORMAL,"recv a request,handler....");
                //         HandlerEntry(new_sock,_inbuff,_cb); //把请求交给该函数处理
                //     }
                //     close(new_sock);
                //     exit(0);
                // }
                // close(new_sock);


                //线程池版
                char buff[10*4048] = {0};
                int n = read(new_sock,buff,sizeof buff - 1); 
                {
                    if(n > 0)
                    {
                        _inbuff = buff;
                        logMessage(NORMAL,"recv a request,handler....");
                        Task t(new_sock,_inbuff,_handler,HandlerEntry);
                        ThreadPool<Task>::GetInstance()->Push(t);
                    }
                }
            }
        }


    private:
        int _list_sock; 
        int _port;
        std::string _inbuff;
        func_t _handler;
    };
};